#include"sever.h"
#include"myepoll.h"
#include"Socket.h"
#include"EventLoop.h"
#include<functional>
#include"Acceptor.h"
#include"TcpConnection.h"
#include"ThreadPool.h"
#include"Buffer.h"

#include<iostream>
#include"agreement.h"
#include"dataProcess.h"

// void Sever::handleData(Buffer &buffer,std::shared_ptr<TcpConnection> conn,MMySql *mysql)
// {
//     std::function<void()>task = [buffer,conn,mysql](){
//         Data::handleData(buffer,conn,mysql);
//     };
//     thread_work->addFunc(task);
// }

void Sever::init(EventLoop * loop)
{
    mainReactor  = loop;
    acceptor = new Acceptor(mainReactor);
    std::function<void(Socket*)> cb = std::bind(&Sever::newConnection,this,std::placeholders::_1);
    acceptor->setNewConnectionCallBack(cb);
    // 线程池，每个子线程对应着一个reactor
    int size = std::thread::hardware_concurrency();
    thread_subReactor = new ThreadPool(size);
    for(int i = 0;i<size;i++){
        subReactor.push_back(new EventLoop());
    }
    // 将每个子线程构建出一个循环
    for(int i = 0;i<size;i++){
        std::function<void()> sub_loop = std::bind(&EventLoop::loop,subReactor[i]);
        thread_subReactor->addFunc(sub_loop);
    }

    mysql = new MMySql("localhost","root","123456","networkDisk",3306);

    
    thread_work = new ThreadPool(20);
}

Sever::Sever(/* args */)
{
}

Sever::Sever(EventLoop *_loop):mainReactor(_loop)
{

}

Sever &Sever::getinstance()
{
    static Sever instance;
    return instance;
}

Sever::~Sever()
{
    delete acceptor;
}


void Sever::newConnection(Socket *seve1_sock)
{
    int random = seve1_sock->getFd()%subReactor.size();
    auto conn = std::make_shared<TcpConnection>(subReactor[random],seve1_sock);
    addConnection(seve1_sock->getFd(),conn);
    std::function<void(Socket*)> cb = std::bind(&Sever::deletConnection,this,std::placeholders::_1);
    conn->setDeleteConnectionCallback(cb);

    conn->setDataHandleCallback([this, conn](Buffer & buffer) {
        // 使用值捕获this指针的副本
        auto self = this;
        
        // 将任务添加到工作线程池
        thread_work->addFunc([buffer, conn, self]() {
            // 通过self指针访问mysql
            Data::handleData(buffer, conn, self->mysql);
        });
    });
    
}

void Sever::deletConnection(Socket *clnt_sock) {
    int fd  = clnt_sock->getFd();
    remConnection(fd);
    std::cout << "deletConnection: Removed, size=" << connection.size() << std::endl;
    // {
    //     std::lock_guard<std::mutex> lock(connMutex);
    //     auto it = connection.find(clnt_sock->getFd());
    //     if (it != connection.end()) {
    //         {
    //             std::unique_lock<std::mutex> connLock(it->second->sendMutex);
    //             while (!it->second->sendQueue.empty()) {
    //                 it->second->sendcv.wait(connLock);
    //             }
    //         }
    //         connection.erase(it);
    //         // std::cout << "deletConnection: Removed, size=" << connection.size() << std::endl;
    //     } else {
    //         std::cout << "deletConnection: fd not found!" << std::endl;
    //     }
    // }
}


ThreadPool* Sever::getThreadWork()
{
    return thread_work;
}

void Sever::addConnection(int fd, std::shared_ptr<TcpConnection> conn)
{
    std::lock_guard<std::mutex> look(connMutex);
    connection[fd] = conn;
}

void Sever::remConnection(int fd)
{
    std::lock_guard<std::mutex> look(connMutex);
    connection.erase(fd);
    remClntLinkConnection(fd);
}


void Sever::addClntLinkConnection(std::string phone, int fd)
{
    std::lock_guard<std::mutex> look(clntLink);
    clntLinkConnection[phone] = fd;
    ConnectionLinkclnt[fd] = phone;
}

void Sever::remClntLinkConnection(int fd)
{
    std::lock_guard<std::mutex> lock(clntLink);
    if(ConnectionLinkclnt.count(fd)){
        mysql->setOnline(std::stoi(ConnectionLinkclnt[fd]),false);
        clntLinkConnection.erase(ConnectionLinkclnt[fd]);
        ConnectionLinkclnt.erase(fd);
    }
}

std::map<int,std::shared_ptr<TcpConnection>> Sever::getConnection()
{
    return connection;
}

std::map<std::string, int> Sever::getClntLinkConnection()
{
    return clntLinkConnection;
}

std::map<int, std::string> Sever::getConnectionLinkclnt()
{
    return ConnectionLinkclnt;
}
